﻿//-----------------------------------------------------------------------
// <copyright file="Layouts.cs" company="LMT">
//     Copyright (c) by La Minh Thuận.
// </copyright>
// <author>thuanla1985@hotmail.com</author>
//-----------------------------------------------------------------------
namespace LMT.Db.SqlClient
{
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.Common;

    /// <summary>
    /// Base class for all Ado Adapter.
    /// </summary>
    /// <typeparam name="T">IEntity constrait</typeparam>
    public class SqlAdapter<T> : DbAdapter<T> where T : IDbEntity, new()
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="OracleAdapter&lt;T&gt;"/> class.
        /// </summary>
        public SqlAdapter()
        {
            this.dataProvider = SqlProvider.Instance;

            if (SqlAdapter<T>.EntityParser == null)
            {
                SqlAdapter<T>.EntityParser = SqlEntity.Instance;
            }
        }

        /// <summary>
        /// Inserts the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <param name="autoMapId">if set to <c>true</c> [auto map id].</param>
        /// <returns></returns>
        public override int Insert(ref T entity, bool autoMapId)
        {
            int result = 0;
            DbCommand command = null;

            try
            {
                command = this.BeginBatchExecute(CommandType.Text, false);

                string insertSql = string.Empty;
                DbParameter[] paras = EntityParser.GetInsertParameters(entity, out insertSql);

                if (autoMapId)
                {
                    insertSql += ";SELECT SCOPE_IDENTITY() as LAST_INCREASED";
                }

                command.CommandText = insertSql;

                if (autoMapId)
                {
                    object sequence = this.ExecuteScalar(command, paras);
                    if (sequence != null)
                    {
                        SqlEntity.Instance.SetAutoIncreaseKey(entity, sequence);
                        result = 1;
                    }
                    else
                    {
                        result = -1;
                    }
                }
                else
                {
                    result = this.ExecuteNonQuery(command, paras);
                }
            }
            finally
            {
                this.CloseBatchExecute(command, false);
            }

            return result;
        }

        /// <summary>
        /// Inserts the specified entities.
        /// </summary>
        /// <param name="entities">The entities.</param>
        /// <param name="autoId">if set to <c>true</c> [auto id].</param>
        /// <returns></returns>
        public override int Insert(List<T> entities, bool autoId)
        {
            if (entities == null)
            {
                throw new ArgumentNullException("entities");
            }

            int result = 0;

            // if the list has only one entity
            if (entities.Count == 1)
            {
                T entity = entities[0];
                result = this.Insert(ref entity, autoId);
            }
            else if (entities.Count > 1)
            {
                string insertSql = string.Empty;
                DbCommand command = null;
                object autoIdValue = 0;
                DbParameter[] paras = null;

                try
                {
                    command = this.BeginBatchExecute(CommandType.Text, false);

                    foreach (T entity in entities)
                    {
                        paras = EntityParser.GetInsertParameters(entity, out insertSql);

                        if (autoId)
                        {
                            insertSql += ";SELECT SCOPE_IDENTITY() as LAST_INCREASED";
                        }

                        if (string.IsNullOrEmpty(command.CommandText))
                        {
                            command.CommandText = insertSql;
                        }

                        if (autoId)
                        {
                            autoIdValue = this.ExecuteScalar(command, paras);
                            if (autoIdValue != null)
                            {
                                SqlEntity.Instance.SetAutoIncreaseKey(entity, autoIdValue);
                                result += 1;
                            }
                            else
                            {
                                result -= 1;
                            }
                        }
                        else
                        {
                            result += this.ExecuteNonQuery(command, paras);
                        }
                    }
                }
                finally
                {
                    this.CloseBatchExecute(command, false);
                }
            }

            return result;
        }

        /// <summary>
        /// Processes the limit return.
        /// </summary>
        /// <param name="maximum">The maximum.</param>
        /// <param name="generatedSql">The generated SQL.</param>
        /// <returns></returns>
        protected override string ProcessLimitReturn(int maximum, string generatedSql)
        {
            generatedSql = generatedSql.Insert(6, string.Format(" TOP {0} ", maximum));
            return generatedSql;
        }
    }
}